﻿using System;
using System.Collections.Generic;
using System.Text;
using Lon.IO.Ports;
using System.IO;

namespace Lon.IO
{
    public class CanDevSimulatorManager : IPeriodRun
    {
        SampleDevCfgManager cfgManager;
        List<SampleDev> devices=new List<SampleDev>();
        Dictionary<int, SampleDev> deviceDict = new Dictionary<int,SampleDev>();
        private ICanDev canPort;
        Queue<OptCmd> optCmdQueue = new Queue<OptCmd>(100);

        public ICanDev CanPort
        {
            get { return canPort; }

            set 
            { 
                canPort = value;
                for(int i=0;i<this.devices.Count;i++)
                {
                    this.devices[i].CanPort = this.canPort;
                }
            }
        }
        public CanDevSimulatorManager(String cfgFileName)
        {
            cfgManager = new SampleDevCfgManager();
            cfgManager.LoadFormXml(cfgFileName);
            foreach (SampleDevParam10 param in cfgManager.Items)
            {
                SampleDev dev = new SampleDev();
                dev.InitFromParam(param);
               
                this.devices.Add(dev);
                deviceDict.Add(dev.DevNo,dev);
            }
        }
   
  
        public void SetValue(int devNo,int cardNum, int analogNum, Int16 val)
        {
            lock (optCmdQueue)
            {
                optCmdQueue.Enqueue(new OptCmd(devNo, cardNum, analogNum, val));
            }
        }
        public void SetDigit(int devNo, int cardNum, int analogNum, Int16 val)
        {
            lock (optCmdQueue)
            {
                OptCmd cmd = new OptCmd(devNo, cardNum, analogNum, val);
                cmd.CmdType = CmdType.Digit;
                optCmdQueue.Enqueue(cmd);
            }
        }
        #region IPeriodRun 成员

        public void Run(ref DateTime startRunTime)
        {
            ValueSet();
           for(int i=0;i<devices.Count;i++)
           {
                devices[i].Run(ref startRunTime);
           }
        }

        private void ValueSet()
        {
            lock (optCmdQueue)
            {

                while (optCmdQueue.Count>0)
                {
                    OptCmd cmd = optCmdQueue.Dequeue();
                    if (!this.deviceDict.ContainsKey(cmd.DevNo))
                    {
                        continue;
                    }
                    if (cmd.CmdType == CmdType.Analog)
                    {
                        this.deviceDict[cmd.DevNo].SetValue(cmd.CardNo, cmd.Index, cmd.Val);
                    }
                    if (cmd.CmdType == CmdType.Digit)
                    {
                        this.deviceDict[cmd.DevNo].SetDigit(cmd.CardNo, cmd.Index, cmd.Val);
                    }
 
                }

                
            }
        }

        #endregion


        public void LoadDefaultVal(String path)
        {
            if (!File.Exists(path))
            {
                return;
            }
            IniDoc cfg = new IniDoc(path);
            cfg.Load();
            for (int i = 0; i < this.devices.Count; i++)
            {
                SampleDev dev = this.devices[i];
                Section sec = cfg.GetSection(String.Format("采集机{0}模拟量", dev.DevNo));
                if (sec == null) continue;
                dev.LoadDefaultAnalogVal(sec);

            }
            for (int i = 0; i < this.devices.Count; i++)
            {
                SampleDev dev = this.devices[i];
                Section sec = cfg.GetSection(String.Format("采集机{0}开关量", dev.DevNo));
                if (sec == null) continue;
                dev.LoadDefaultKglVal(sec);

            }
        }

        public void SaveCurrentVal(string path)
        {
            IniDoc ini=new IniDoc(path);
            for (int i = 0; i < this.devices.Count; i++)
            {
                SampleDev dev = this.devices[i];
                for (int j = 0; j < dev.Cards.Count; j++)
                {
                    SetKgl(ini, dev, j);
                    SetAnalog(ini, dev, j);
                }       
            }
            ini.Save();
        }

        private static void SetAnalog(IniDoc ini, SampleDev dev, int cardIndex)
        {
            AnalogValue[] vals = dev.Cards[cardIndex].AnalogValues;
            if (vals.Length == 0)
            {
                return;
            }
            StringBuilder sb = new StringBuilder();
            for (int k = 0; k < vals.Length - 1; k++)
            {
                sb.AppendFormat("{0},", vals[k]);
            }
            sb.Append(vals[vals.Length - 1]);
            String secName = String.Format("采集机{0}模拟量", dev.DevNo);
            String keyName = dev.Cards[cardIndex].CardNo.ToString();
            ini.SetValue(secName, keyName, sb.ToString());
        }

        private static void SetKgl(IniDoc ini, SampleDev dev, int cardIndex)
        {
            DigitValue[] vals = dev.Cards[cardIndex].DigitValues;
            if (vals.Length == 0)
            {
                return;
            }
            StringBuilder sb = new StringBuilder();
            for (int k = 0; k < vals.Length - 1; k++)
            {
                sb.AppendFormat("{0},", vals[k]);
            }
            sb.Append(vals[vals.Length - 1]);
            String secName = String.Format("采集机{0}开关量", dev.DevNo);
            String keyName = dev.Cards[cardIndex].CardNo.ToString();
            ini.SetValue(secName, keyName, sb.ToString());
        }
    }
}
